{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import re\n",
    "import csv\n",
    "import urllib.request\n",
    "import urllib.parse\n",
    "import urllib.robotparser\n",
    "from bs4 import BeautifulSoup\n",
    "import lxml.html\n",
    "from lxml.cssselect import CSSSelector\n",
    "import os\n",
    "import pickle\n",
    "import zlib\n",
    "import shutil\n",
    "from datetime import datetime, timedelta\n",
    "from pymongo import MongoClient\n",
    "from bson.binary import Binary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Throttle:\n",
    "    \"\"\"\n",
    "    Add a delay between downloads to the same domain\n",
    "    \"\"\"\n",
    "    def __init__(self,delay):\n",
    "        # amount of delay between downloads for each domain\n",
    "        self.delay = delay\n",
    "        # timestamp of when a domain was last accessed\n",
    "        self.domains = {}\n",
    "        \n",
    "    def wait(self,url):\n",
    "        domain = urllib.parse.urlparse(url).netloc\n",
    "        last_accessed = self.domains.get(domain)\n",
    "        if self.delay > 0 and last_accessed is not None:\n",
    "            sleep_secs = self.delay - (datetime.now() - last_accessed).seconds\n",
    "            if sleep_secs > 0:\n",
    "                # domain has been accessed recently so need to sleep\n",
    "                time.sleep(sleep_secs)\n",
    "        # update the last accessed time\n",
    "        self.domains[domain] = datetime.now()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Downloader:\n",
    "    def __init__(self, delay=5, user_agent='wswp', proxies=None, num_retries=1, cache=None):\n",
    "        self.throttle = Throttle(delay)\n",
    "        self.user_agent = user_agent\n",
    "        self.proxies = proxies\n",
    "        self.num_retries = num_retries\n",
    "        self.cache = cache\n",
    "    def __call__(self, url):\n",
    "        result = None\n",
    "        if self.cache:\n",
    "            try:\n",
    "                result = self.cache[url]\n",
    "            except KeyError:\n",
    "                # url is not available in cache\n",
    "                pass\n",
    "            else:\n",
    "                if self.num_retries > 0 and 500 <= result['code'] < 600:\n",
    "                    #server error so ignore result from cache and re-download\n",
    "                    result = None\n",
    "        if result is None:\n",
    "            # result was not loaded from cache so still need to download\n",
    "            self.throttle.wait(url)\n",
    "            proxy = random.choice(self.proxies) if self.proxies else None\n",
    "            headers = {'User-agent':self.user_agent}\n",
    "            result = self.download(url, headers, proxy, self.num_retries)\n",
    "            if result is None:\n",
    "                return None\n",
    "            if self.cache:\n",
    "                # save result to cache\n",
    "                self.cache[url] = result\n",
    "        return result['html']\n",
    "    def download(self, url, headers, proxy, num_retries, data=None):\n",
    "        print('Downloading:',url)\n",
    "        request = urllib.request.Request(url,headers=headers)\n",
    "        opener = urllib.request.build_opener()\n",
    "        if proxy:\n",
    "            proxy_params = {urllib.parse.urlparse(url).scheme: proxy}\n",
    "            opener.add_handler(urllib.request.ProxyHandler(proxy_params))\n",
    "        try:\n",
    "            response = opener.open(request)\n",
    "        except urllib.request.URLError as e:\n",
    "            print('Download error:',e.reason)\n",
    "            response = None\n",
    "            if num_retries>0 and hasattr(e,'code') and 500<=e.code<600:\n",
    "                return self.download(url,headers,proxy,num_retries-1)\n",
    "        if response:\n",
    "            return {'html':response.read().decode('utf-8'),'code':response.code}\n",
    "        else:\n",
    "            return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def link_crawler(send_url, link_regex, delay=1, max_depth=2, scrape_callback=None, cache=None):\n",
    "    rp = urllib.robotparser.RobotFileParser()\n",
    "    rp.set_url(urllib.parse.urljoin(send_url,'/robots.txt'))\n",
    "    rp.read()\n",
    "    user_agent = \"Baiduspider\"\n",
    "    crawl_queue = [send_url]\n",
    "    seen = {send_url:0}\n",
    "    D = Downloader(delay=delay, user_agent=user_agent, proxies=None, num_retries=2, cache=cache)\n",
    "    while crawl_queue:\n",
    "        url = crawl_queue.pop()\n",
    "        depth = seen[url]\n",
    "        if depth != max_depth:\n",
    "            # chec url passes robots.txt restrictions\n",
    "            if rp.can_fetch(user_agent,url):\n",
    "                html = D(url)\n",
    "                if html == None:\n",
    "                    continue;\n",
    "                links = []\n",
    "                if scrape_callback:\n",
    "                    links.extend(scrape_callback(url, html) or [])\n",
    "                if link_regex:\n",
    "                    # filter for links matching our regular expression\n",
    "                    links.extend(link for link in get_links(html) if re.match(link_regex, link))\n",
    "                    # print('肯定会执行')\n",
    "                for link in links:\n",
    "                    # from absolute link\n",
    "                    link = urllib.parse.urljoin(send_url,link)\n",
    "                    # check if have alreday seen this link\n",
    "                    if link not in seen:\n",
    "                        seen[link] = depth + 1\n",
    "                        crawl_queue.append(link)\n",
    "            else:\n",
    "                print('Blocked by robots.txt:',url)\n",
    "def get_links(html):\n",
    "    \"\"\"\n",
    "    Return a list of links from html\n",
    "    \"\"\"\n",
    "    # a regular expression to extract all links from the webpage\n",
    "    webpage_regex = re.compile('<a[^>]+href=[\"\\'](.*?)[\"\\']',re.IGNORECASE)\n",
    "    # list of all links from the webpaeg\n",
    "    return webpage_regex.findall(html)\n",
    "FIELDS = ('area', 'population', 'iso', 'country', 'capital', 'continent', 'tld', 'currency_code', 'currency_name', 'phone', 'postal_code_format', 'postal_code_regex', 'languages', 'neighbours')\n",
    "def scrape_callback(url, html):\n",
    "    if re.search('/view/', url):\n",
    "        tree = lxml.html.fromstring(html)\n",
    "        row = [tree.cssselect('table > tr#places_%s__row > td.w2p_fw' % field)[0].text_content() for field in FIELDS]\n",
    "        print(url, row)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DiskCache:\n",
    "    def __init__(self, cache_dir='cache', compress=False, expires=timedelta(days=30)):\n",
    "        self.cache_dir = cache_dir\n",
    "        self.compress = compress\n",
    "        self.expires = expires\n",
    "    def url_to_path(self, url):\n",
    "        '''\n",
    "        Create file system path for this URL\n",
    "        '''\n",
    "        components = urllib.parse.urlsplit(url)\n",
    "        # append index.html to empth paths\n",
    "        path = components.path\n",
    "        if not path:\n",
    "            path = '/index'\n",
    "        elif path.endswith('/'):\n",
    "            path += 'index'\n",
    "        path += '.html'\n",
    "        filename = components.netloc + path + components.query\n",
    "        # replace invalid characters\n",
    "        filename = re.sub('[^/0-9a-zA-Z\\-.,;_ ]', '_', filename)\n",
    "        # restrict maximum number of characters\n",
    "        filename = '/'.join(segment[:255] for segment in filename.split('/'))\n",
    "        return os.path.join(self.cache_dir, filename)\n",
    "    def __getitem__(self, url):\n",
    "        \"\"\"\n",
    "        Load data from disk for this URL\n",
    "        \"\"\"\n",
    "        path = self.url_to_path(url)\n",
    "        if os.path.exists(path):\n",
    "            with open(path, 'rb') as fp:\n",
    "                data = fp.read()\n",
    "                if self.compress:\n",
    "                    data = zlib.decompress(data)\n",
    "                result, timestamp = pickle.loads(data)\n",
    "                if self.has_expired(timestamp):\n",
    "                    raise KeyError(url + ' has expired')\n",
    "                return result\n",
    "        else:\n",
    "            # url has not yet been cached\n",
    "            raise KeyError(url + ' does not exist')\n",
    "    def __setitem__(self, url, result):\n",
    "        \"\"\"\n",
    "        Save data to disk for this URL\n",
    "        \"\"\"\n",
    "        path = self.url_to_path(url)\n",
    "        folder = os.path.dirname(path)\n",
    "        if not os.path.exists(folder):\n",
    "            os.makedirs(folder)\n",
    "        data = pickle.dumps((result, datetime.utcnow()))\n",
    "        if self.compress:\n",
    "            data = zlib.compress(data)\n",
    "        with open(path, 'wb') as fp:\n",
    "            fp.write(data)\n",
    "    def __delitem__(self, url):\n",
    "        \"\"\"\n",
    "        Remove the value at this key and any empty parent sub-directories\n",
    "        \"\"\"\n",
    "        path = self._key_path(url)\n",
    "        try:\n",
    "            os.remove(path)\n",
    "            os.removedirs(os.path.dirname(path))\n",
    "        except OSError:\n",
    "            pass\n",
    "    def has_expired(self, timestamp):\n",
    "        \"\"\"Return whether this timestamp has expired\n",
    "        \"\"\"\n",
    "        return datetime.utcnow() > (timestamp + self.expires)\n",
    "    def clear(self):\n",
    "        \"\"\"Remove all the cached values\n",
    "        \"\"\"\n",
    "        if os.path.exists(self.cache_dir):\n",
    "            shutil.rmtree(self.cache_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.webscraping.com/places/default/view/Zimbabwe-252 ['390,580 square kilometres', '11,651,858', 'ZW', 'Zimbabwe', 'Harare', 'AF', '.zw', 'ZWL', 'Dollar', '263', '', '', 'en-ZW,sn,nr,nd', 'ZA MZ BW ZM ']\n",
      "http://example.webscraping.com/places/default/view/Zambia-251 ['752,614 square kilometres', '13,460,305', 'ZM', 'Zambia', 'Lusaka', 'AF', '.zm', 'ZMW', 'Kwacha', '260', '#####', '^(\\\\d{5})$', 'en-ZM,bem,loz,lun,lue,ny,toi', 'ZW TZ MZ CD NA MW AO ']\n",
      "http://example.webscraping.com/places/default/view/Yemen-250 ['527,970 square kilometres', '23,495,361', 'YE', 'Yemen', 'Sanaa', 'AS', '.ye', 'YER', 'Rial', '967', '', '', 'ar-YE', 'SA OM ']\n",
      "http://example.webscraping.com/places/default/view/Western-Sahara-249 ['266,000 square kilometres', '273,008', 'EH', 'Western Sahara', 'El-Aaiun', 'AF', '.eh', 'MAD', 'Dirham', '212', '', '', 'ar,mey', 'DZ MR MA ']\n",
      "http://example.webscraping.com/places/default/view/Wallis-and-Futuna-248 ['274 square kilometres', '16,025', 'WF', 'Wallis and Futuna', 'Mata Utu', 'OC', '.wf', 'XPF', 'Franc', '681', '#####', '^(986\\\\d{2})$', 'wls,fud,fr-WF', ' ']\n",
      "http://example.webscraping.com/places/default/view/Vietnam-247 ['329,560 square kilometres', '89,571,130', 'VN', 'Vietnam', 'Hanoi', 'AS', '.vn', 'VND', 'Dong', '84', '######', '^(\\\\d{6})$', 'vi,en,fr,zh,km', 'CN LA KH ']\n",
      "http://example.webscraping.com/places/default/view/Venezuela-246 ['912,050 square kilometres', '27,223,228', 'VE', 'Venezuela', 'Caracas', 'SA', '.ve', 'VEF', 'Bolivar', '58', '####', '^(\\\\d{4})$', 'es-VE', 'GY BR CO ']\n",
      "http://example.webscraping.com/places/default/view/Vatican-245 ['0 square kilometres', '921', 'VA', 'Vatican', 'Vatican City', 'EU', '.va', 'EUR', 'Euro', '379', '#####', '^(\\\\d{5})$', 'la,it,fr', 'IT ']\n",
      "http://example.webscraping.com/places/default/view/Vanuatu-244 ['12,200 square kilometres', '221,552', 'VU', 'Vanuatu', 'Port Vila', 'OC', '.vu', 'VUV', 'Vatu', '678', '', '', 'bi,en-VU,fr-VU', ' ']\n",
      "http://example.webscraping.com/places/default/view/Uzbekistan-243 ['447,400 square kilometres', '27,865,738', 'UZ', 'Uzbekistan', 'Tashkent', 'AS', '.uz', 'UZS', 'Som', '998', '######', '^(\\\\d{6})$', 'uz,ru,tg', 'TM AF KG TJ KZ ']\n",
      "http://example.webscraping.com/places/default/view/Uruguay-242 ['176,220 square kilometres', '3,477,000', 'UY', 'Uruguay', 'Montevideo', 'SA', '.uy', 'UYU', 'Peso', '598', '#####', '^(\\\\d{5})$', 'es-UY', 'BR AR ']\n",
      "http://example.webscraping.com/places/default/view/United-States-Minor-Outlying-Islands-241 ['0 square kilometres', '0', 'UM', 'United States Minor Outlying Islands', '', 'OC', '.um', 'USD', 'Dollar', '1', '', '', 'en-UM', ' ']\n",
      "http://example.webscraping.com/places/default/view/United-States-240 ['9,629,091 square kilometres', '310,232,863', 'US', 'United States', 'Washington', 'NA', '.us', 'USD', 'Dollar', '1', '#####-####', '^\\\\d{5}(-\\\\d{4})?$', 'en-US,es-US,haw,fr', 'CA MX CU ']\n",
      "http://example.webscraping.com/places/default/view/United-Kingdom-239 ['244,820 square kilometres', '62,348,447', 'GB', 'United Kingdom', 'London', 'EU', '.uk', 'GBP', 'Pound', '44', '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA', '^(([A-Z]\\\\d{2}[A-Z]{2})|([A-Z]\\\\d{3}[A-Z]{2})|([A-Z]{2}\\\\d{2}[A-Z]{2})|([A-Z]{2}\\\\d{3}[A-Z]{2})|([A-Z]\\\\d[A-Z]\\\\d[A-Z]{2})|([A-Z]{2}\\\\d[A-Z]\\\\d[A-Z]{2})|(GIR0AA))$', 'en-GB,cy-GB,gd', 'IE ']\n",
      "http://example.webscraping.com/places/default/view/United-Arab-Emirates-238 ['82,880 square kilometres', '4,975,593', 'AE', 'United Arab Emirates', 'Abu Dhabi', 'AS', '.ae', 'AED', 'Dirham', '971', '', '', 'ar-AE,fa,en,hi,ur', 'SA OM ']\n",
      "http://example.webscraping.com/places/default/view/Ukraine-237 ['603,700 square kilometres', '45,415,596', 'UA', 'Ukraine', 'Kiev', 'EU', '.ua', 'UAH', 'Hryvnia', '380', '#####', '^(\\\\d{5})$', 'uk,ru-UA,rom,pl,hu', 'PL MD HU SK BY RO RU ']\n",
      "http://example.webscraping.com/places/default/view/Uganda-236 ['236,040 square kilometres', '33,398,682', 'UG', 'Uganda', 'Kampala', 'AF', '.ug', 'UGX', 'Shilling', '256', '', '', 'en-UG,lg,sw,ar', 'TZ KE SS CD RW ']\n",
      "http://example.webscraping.com/places/default/view/US-Virgin-Islands-235 ['352 square kilometres', '108,708', 'VI', 'U.S. Virgin Islands', 'Charlotte Amalie', 'NA', '.vi', 'USD', 'Dollar', '+1-340', '#####-####', '^\\\\d{5}(-\\\\d{4})?$', 'en-VI', ' ']\n",
      "http://example.webscraping.com/places/default/view/Tuvalu-234 ['26 square kilometres', '10,472', 'TV', 'Tuvalu', 'Funafuti', 'OC', '.tv', 'AUD', 'Dollar', '688', '', '', 'tvl,en,sm,gil', ' ']\n",
      "http://example.webscraping.com/places/default/view/Turks-and-Caicos-Islands-233 ['430 square kilometres', '20,556', 'TC', 'Turks and Caicos Islands', 'Cockburn Town', 'NA', '.tc', 'USD', 'Dollar', '+1-649', 'TKCA 1ZZ', '^(TKCA 1ZZ)$', 'en-TC', ' ']\n",
      "http://example.webscraping.com/places/default/view/Turkmenistan-232 ['488,100 square kilometres', '4,940,916', 'TM', 'Turkmenistan', 'Ashgabat', 'AS', '.tm', 'TMT', 'Manat', '993', '######', '^(\\\\d{6})$', 'tk,ru,uz', 'AF IR UZ KZ ']\n",
      "http://example.webscraping.com/places/default/view/Turkey-231 ['780,580 square kilometres', '77,804,122', 'TR', 'Turkey', 'Ankara', 'AS', '.tr', 'TRY', 'Lira', '90', '#####', '^(\\\\d{5})$', 'tr-TR,ku,diq,az,av', 'SY GE IQ IR GR AM AZ BG ']\n",
      "http://example.webscraping.com/places/default/view/Tunisia-230 ['163,610 square kilometres', '10,589,025', 'TN', 'Tunisia', 'Tunis', 'AF', '.tn', 'TND', 'Dinar', '216', '####', '^(\\\\d{4})$', 'ar-TN,fr', 'DZ LY ']\n",
      "http://example.webscraping.com/places/default/view/Trinidad-and-Tobago-229 ['5,128 square kilometres', '1,228,691', 'TT', 'Trinidad and Tobago', 'Port of Spain', 'NA', '.tt', 'TTD', 'Dollar', '+1-868', '', '', 'en-TT,hns,fr,es,zh', ' ']\n",
      "http://example.webscraping.com/places/default/view/Tonga-228 ['748 square kilometres', '122,580', 'TO', 'Tonga', \"Nuku'alofa\", 'OC', '.to', 'TOP', \"Pa'anga\", '676', '', '', 'to,en-TO', ' ']\n",
      "http://example.webscraping.com/places/default/view/Tokelau-227 ['10 square kilometres', '1,466', 'TK', 'Tokelau', '', 'OC', '.tk', 'NZD', 'Dollar', '690', '', '', 'tkl,en-TK', ' ']\n",
      "http://example.webscraping.com/places/default/view/Togo-226 ['56,785 square kilometres', '6,587,239', 'TG', 'Togo', 'Lome', 'AF', '.tg', 'XOF', 'Franc', '228', '', '', 'fr-TG,ee,hna,kbp,dag,ha', 'BJ GH BF ']\n",
      "http://example.webscraping.com/places/default/view/Thailand-225 ['514,000 square kilometres', '67,089,500', 'TH', 'Thailand', 'Bangkok', 'AS', '.th', 'THB', 'Baht', '66', '#####', '^(\\\\d{5})$', 'th,en', 'LA MM KH MY ']\n",
      "http://example.webscraping.com/places/default/view/Tanzania-224 ['945,087 square kilometres', '41,892,895', 'TZ', 'Tanzania', 'Dodoma', 'AF', '.tz', 'TZS', 'Shilling', '255', '', '', 'sw-TZ,en,ar', 'MZ KE CD RW ZM BI UG MW ']\n",
      "http://example.webscraping.com/places/default/view/Tajikistan-223 ['143,100 square kilometres', '7,487,489', 'TJ', 'Tajikistan', 'Dushanbe', 'AS', '.tj', 'TJS', 'Somoni', '992', '######', '^(\\\\d{6})$', 'tg,ru', 'CN AF KG UZ ']\n",
      "http://example.webscraping.com/places/default/view/Taiwan-222 ['35,980 square kilometres', '22,894,384', 'TW', 'Taiwan', 'Taipei', 'AS', '.tw', 'TWD', 'Dollar', '886', '#####', '^(\\\\d{5})$', 'zh-TW,zh,nan,hak', ' ']\n",
      "http://example.webscraping.com/places/default/view/Syria-221 ['185,180 square kilometres', '22,198,110', 'SY', 'Syria', 'Damascus', 'AS', '.sy', 'SYP', 'Pound', '963', '', '', 'ar-SY,ku,hy,arc,fr,en', 'IQ JO IL TR LB ']\n",
      "http://example.webscraping.com/places/default/view/Switzerland-220 ['41,290 square kilometres', '7,581,000', 'CH', 'Switzerland', 'Berne', 'EU', '.ch', 'CHF', 'Franc', '41', '####', '^(\\\\d{4})$', 'de-CH,fr-CH,it-CH,rm', 'DE IT LI FR AT ']\n",
      "http://example.webscraping.com/places/default/view/Sweden-219 ['449,964 square kilometres', '9,555,893', 'SE', 'Sweden', 'Stockholm', 'EU', '.se', 'SEK', 'Krona', '46', '### ##', '^(?:SE)*(\\\\d{5})$', 'sv-SE,se,sma,fi-SE', 'NO FI ']\n",
      "http://example.webscraping.com/places/default/view/Swaziland-218 ['17,363 square kilometres', '1,354,051', 'SZ', 'Swaziland', 'Mbabane', 'AF', '.sz', 'SZL', 'Lilangeni', '268', '@###', '^([A-Z]\\\\d{3})$', 'en-SZ,ss-SZ', 'ZA MZ ']\n",
      "http://example.webscraping.com/places/default/view/Svalbard-and-Jan-Mayen-217 ['62,049 square kilometres', '2,550', 'SJ', 'Svalbard and Jan Mayen', 'Longyearbyen', 'EU', '.sj', 'NOK', 'Krone', '47', '', '', 'no,ru', ' ']\n",
      "http://example.webscraping.com/places/default/view/Suriname-216 ['163,270 square kilometres', '492,829', 'SR', 'Suriname', 'Paramaribo', 'SA', '.sr', 'SRD', 'Dollar', '597', '', '', 'nl-SR,en,srn,hns,jv', 'GY BR GF ']\n",
      "http://example.webscraping.com/places/default/view/Sudan-215 ['1,861,484 square kilometres', '35,000,000', 'SD', 'Sudan', 'Khartoum', 'AF', '.sd', 'SDG', 'Pound', '249', '#####', '^(\\\\d{5})$', 'ar-SD,en,fia', 'SS TD EG ET ER LY CF ']\n",
      "http://example.webscraping.com/places/default/view/Sri-Lanka-214 ['65,610 square kilometres', '21,513,990', 'LK', 'Sri Lanka', 'Colombo', 'AS', '.lk', 'LKR', 'Rupee', '94', '#####', '^(\\\\d{5})$', 'si,ta,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Spain-213 ['504,782 square kilometres', '46,505,963', 'ES', 'Spain', 'Madrid', 'EU', '.es', 'EUR', 'Euro', '34', '#####', '^(\\\\d{5})$', 'es-ES,ca,gl,eu,oc', 'AD PT GI FR MA ']\n",
      "http://example.webscraping.com/places/default/view/South-Sudan-212 ['644,329 square kilometres', '8,260,490', 'SS', 'South Sudan', 'Juba', 'AF', '', 'SSP', 'Pound', '211', '', '', 'en', 'CD CF ET KE SD UG  ']\n",
      "http://example.webscraping.com/places/default/view/South-Korea-211 ['98,480 square kilometres', '48,422,644', 'KR', 'South Korea', 'Seoul', 'AS', '.kr', 'KRW', 'Won', '82', 'SEOUL ###-###', '^(?:SEOUL)*(\\\\d{6})$', 'ko-KR,en', 'KP ']\n",
      "http://example.webscraping.com/places/default/view/South-Georgia-and-the-South-Sandwich-Islands-210 ['3,903 square kilometres', '30', 'GS', 'South Georgia and the South Sandwich Islands', 'Grytviken', 'AN', '.gs', 'GBP', 'Pound', '', '', '', 'en', ' ']\n",
      "http://example.webscraping.com/places/default/view/South-Africa-209 ['1,219,912 square kilometres', '49,000,000', 'ZA', 'South Africa', 'Pretoria', 'AF', '.za', 'ZAR', 'Rand', '27', '####', '^(\\\\d{4})$', 'zu,xh,af,nso,en-ZA,tn,st,ts,ss,ve,nr', 'ZW SZ MZ BW NA LS ']\n",
      "http://example.webscraping.com/places/default/view/Somalia-208 ['637,657 square kilometres', '10,112,453', 'SO', 'Somalia', 'Mogadishu', 'AF', '.so', 'SOS', 'Shilling', '252', '@@  #####', '^([A-Z]{2}\\\\d{5})$', 'so-SO,ar-SO,it,en-SO', 'ET KE DJ ']\n",
      "http://example.webscraping.com/places/default/view/Solomon-Islands-207 ['28,450 square kilometres', '559,198', 'SB', 'Solomon Islands', 'Honiara', 'OC', '.sb', 'SBD', 'Dollar', '677', '', '', 'en-SB,tpi', ' ']\n",
      "http://example.webscraping.com/places/default/view/Slovenia-206 ['20,273 square kilometres', '2,007,000', 'SI', 'Slovenia', 'Ljubljana', 'EU', '.si', 'EUR', 'Euro', '386', '####', '^(?:SI)*(\\\\d{4})$', 'sl,sh', 'HU IT HR AT ']\n",
      "http://example.webscraping.com/places/default/view/Slovakia-205 ['48,845 square kilometres', '5,455,000', 'SK', 'Slovakia', 'Bratislava', 'EU', '.sk', 'EUR', 'Euro', '421', '### ##', '^(\\\\d{5})$', 'sk,hu', 'PL HU CZ UA AT ']\n",
      "http://example.webscraping.com/places/default/view/Sint-Maarten-204 ['34 square kilometres', '37,429', 'SX', 'Sint Maarten', 'Philipsburg', 'NA', '.sx', 'ANG', 'Guilder', '599', '', '', 'nl,en', 'MF ']\n",
      "http://example.webscraping.com/places/default/view/Singapore-203 ['692 square kilometres', '4,701,069', 'SG', 'Singapore', 'Singapur', 'AS', '.sg', 'SGD', 'Dollar', '65', '######', '^(\\\\d{6})$', 'cmn,en-SG,ms-SG,ta-SG,zh-SG', ' ']\n",
      "http://example.webscraping.com/places/default/view/Sierra-Leone-202 ['71,740 square kilometres', '5,245,695', 'SL', 'Sierra Leone', 'Freetown', 'AF', '.sl', 'SLL', 'Leone', '232', '', '', 'en-SL,men,tem', 'LR GN ']\n",
      "http://example.webscraping.com/places/default/view/Seychelles-201 ['455 square kilometres', '88,340', 'SC', 'Seychelles', 'Victoria', 'AF', '.sc', 'SCR', 'Rupee', '248', '', '', 'en-SC,fr-SC', ' ']\n",
      "http://example.webscraping.com/places/default/view/Serbia-and-Montenegro-200 ['102,350 square kilometres', '10,829,175', 'CS', 'Serbia and Montenegro', 'Belgrade', 'EU', '.cs', 'RSD', 'Dinar', '381', '#####', '^(\\\\d{5})$', 'cu,hu,sq,sr', 'AL HU MK RO HR BA BG ']\n",
      "http://example.webscraping.com/places/default/view/Serbia-199 ['88,361 square kilometres', '7,344,847', 'RS', 'Serbia', 'Belgrade', 'EU', '.rs', 'RSD', 'Dinar', '381', '######', '^(\\\\d{6})$', 'sr,hu,bs,rom', 'AL HU MK RO HR BA BG ME XK ']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.webscraping.com/places/default/view/Senegal-198 ['196,190 square kilometres', '12,323,252', 'SN', 'Senegal', 'Dakar', 'AF', '.sn', 'XOF', 'Franc', '221', '#####', '^(\\\\d{5})$', 'fr-SN,wo,fuc,mnk', 'GN MR GW GM ML ']\n",
      "http://example.webscraping.com/places/default/view/Saudi-Arabia-197 ['1,960,582 square kilometres', '25,731,776', 'SA', 'Saudi Arabia', 'Riyadh', 'AS', '.sa', 'SAR', 'Rial', '966', '#####', '^(\\\\d{5})$', 'ar-SA', 'QA OM IQ YE JO AE KW ']\n",
      "http://example.webscraping.com/places/default/view/Sao-Tome-and-Principe-196 ['1,001 square kilometres', '175,808', 'ST', 'Sao Tome and Principe', 'Sao Tome', 'AF', '.st', 'STD', 'Dobra', '239', '', '', 'pt-ST', ' ']\n",
      "http://example.webscraping.com/places/default/view/San-Marino-195 ['61 square kilometres', '31,477', 'SM', 'San Marino', 'San Marino', 'EU', '.sm', 'EUR', 'Euro', '378', '4789#', '^(4789\\\\d)$', 'it-SM', 'IT ']\n",
      "http://example.webscraping.com/places/default/view/Samoa-194 ['2,944 square kilometres', '192,001', 'WS', 'Samoa', 'Apia', 'OC', '.ws', 'WST', 'Tala', '685', '', '', 'sm,en-WS', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Vincent-and-the-Grenadines-193 ['389 square kilometres', '104,217', 'VC', 'Saint Vincent and the Grenadines', 'Kingstown', 'NA', '.vc', 'XCD', 'Dollar', '+1-784', '', '', 'en-VC,fr', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Pierre-and-Miquelon-192 ['242 square kilometres', '7,012', 'PM', 'Saint Pierre and Miquelon', 'Saint-Pierre', 'NA', '.pm', 'EUR', 'Euro', '508', '#####', '^(97500)$', 'fr-PM', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Martin-191 ['53 square kilometres', '35,925', 'MF', 'Saint Martin', 'Marigot', 'NA', '.gp', 'EUR', 'Euro', '590', '### ###', '', 'fr', 'SX ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Lucia-190 ['616 square kilometres', '160,922', 'LC', 'Saint Lucia', 'Castries', 'NA', '.lc', 'XCD', 'Dollar', '+1-758', '', '', 'en-LC', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Kitts-and-Nevis-189 ['261 square kilometres', '51,134', 'KN', 'Saint Kitts and Nevis', 'Basseterre', 'NA', '.kn', 'XCD', 'Dollar', '+1-869', '', '', 'en-KN', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Helena-188 ['410 square kilometres', '7,460', 'SH', 'Saint Helena', 'Jamestown', 'AF', '.sh', 'SHP', 'Pound', '290', 'STHL 1ZZ', '^(STHL1ZZ)$', 'en-SH', ' ']\n",
      "http://example.webscraping.com/places/default/view/Saint-Barthelemy-187 ['21 square kilometres', '8,450', 'BL', 'Saint Barthelemy', 'Gustavia', 'NA', '.gp', 'EUR', 'Euro', '590', '### ###', '', 'fr', ' ']\n",
      "http://example.webscraping.com/places/default/view/Rwanda-186 ['26,338 square kilometres', '11,055,976', 'RW', 'Rwanda', 'Kigali', 'AF', '.rw', 'RWF', 'Franc', '250', '', '', 'rw,en-RW,fr-RW,sw', 'TZ CD BI UG ']\n",
      "http://example.webscraping.com/places/default/view/Russia-185 ['17,100,000 square kilometres', '140,702,000', 'RU', 'Russia', 'Moscow', 'EU', '.ru', 'RUB', 'Ruble', '7', '######', '^(\\\\d{6})$', 'ru,tt,xal,cau,ady,kv,ce,tyv,cv,udm,tut,mns,bua,myv,mdf,chm,ba,inh,tut,kbd,krc,ava,sah,nog', 'GE CN BY UA KZ LV PL EE LT FI MN NO AZ KP ']\n",
      "http://example.webscraping.com/places/default/view/Romania-184 ['237,500 square kilometres', '21,959,278', 'RO', 'Romania', 'Bucharest', 'EU', '.ro', 'RON', 'Leu', '40', '######', '^(\\\\d{6})$', 'ro,hu,rom', 'MD HU UA CS BG RS ']\n",
      "http://example.webscraping.com/places/default/view/Reunion-183 ['2,517 square kilometres', '776,948', 'RE', 'Reunion', 'Saint-Denis', 'AF', '.re', 'EUR', 'Euro', '262', '#####', '^((97|98)(4|7|8)\\\\d{2})$', 'fr-RE', ' ']\n",
      "http://example.webscraping.com/places/default/view/Republic-of-the-Congo-182 ['342,000 square kilometres', '3,039,126', 'CG', 'Republic of the Congo', 'Brazzaville', 'AF', '.cg', 'XAF', 'Franc', '242', '', '', 'fr-CG,kg,ln-CG', 'CF GA CD CM AO ']\n",
      "http://example.webscraping.com/places/default/view/Qatar-181 ['11,437 square kilometres', '840,926', 'QA', 'Qatar', 'Doha', 'AS', '.qa', 'QAR', 'Rial', '974', '', '', 'ar-QA,es', 'SA ']\n",
      "http://example.webscraping.com/places/default/view/Puerto-Rico-180 ['9,104 square kilometres', '3,916,632', 'PR', 'Puerto Rico', 'San Juan', 'NA', '.pr', 'USD', 'Dollar', '+1-787 and 1-939', '#####-####', '^(\\\\d{9})$', 'en-PR,es-PR', ' ']\n",
      "http://example.webscraping.com/places/default/view/Portugal-179 ['92,391 square kilometres', '10,676,000', 'PT', 'Portugal', 'Lisbon', 'EU', '.pt', 'EUR', 'Euro', '351', '####-###', '^(\\\\d{7})$', 'pt-PT,mwl', 'ES ']\n",
      "http://example.webscraping.com/places/default/view/Poland-178 ['312,685 square kilometres', '38,500,000', 'PL', 'Poland', 'Warsaw', 'EU', '.pl', 'PLN', 'Zloty', '48', '##-###', '^(\\\\d{5})$', 'pl', 'DE LT SK CZ BY UA RU ']\n",
      "http://example.webscraping.com/places/default/view/Pitcairn-177 ['47 square kilometres', '46', 'PN', 'Pitcairn', 'Adamstown', 'OC', '.pn', 'NZD', 'Dollar', '870', '', '', 'en-PN', ' ']\n",
      "http://example.webscraping.com/places/default/view/Philippines-176 ['300,000 square kilometres', '99,900,177', 'PH', 'Philippines', 'Manila', 'AS', '.ph', 'PHP', 'Peso', '63', '####', '^(\\\\d{4})$', 'tl,en-PH,fil', ' ']\n",
      "http://example.webscraping.com/places/default/view/Peru-175 ['1,285,220 square kilometres', '29,907,003', 'PE', 'Peru', 'Lima', 'SA', '.pe', 'PEN', 'Sol', '51', '', '', 'es-PE,qu,ay', 'EC CL BO BR CO ']\n",
      "http://example.webscraping.com/places/default/view/Paraguay-174 ['406,750 square kilometres', '6,375,830', 'PY', 'Paraguay', 'Asuncion', 'SA', '.py', 'PYG', 'Guarani', '595', '####', '^(\\\\d{4})$', 'es-PY,gn', 'BO BR AR ']\n",
      "http://example.webscraping.com/places/default/view/Papua-New-Guinea-173 ['462,840 square kilometres', '6,064,515', 'PG', 'Papua New Guinea', 'Port Moresby', 'OC', '.pg', 'PGK', 'Kina', '675', '###', '^(\\\\d{3})$', 'en-PG,ho,meu,tpi', 'ID ']\n",
      "http://example.webscraping.com/places/default/view/Panama-172 ['78,200 square kilometres', '3,410,676', 'PA', 'Panama', 'Panama City', 'NA', '.pa', 'PAB', 'Balboa', '507', '', '', 'es-PA,en', 'CR CO ']\n",
      "http://example.webscraping.com/places/default/view/Palestinian-Territory-171 ['5,970 square kilometres', '3,800,000', 'PS', 'Palestinian Territory', 'East Jerusalem', 'AS', '.ps', 'ILS', 'Shekel', '970', '', '', 'ar-PS', 'JO IL ']\n",
      "http://example.webscraping.com/places/default/view/Palau-170 ['458 square kilometres', '19,907', 'PW', 'Palau', 'Melekeok', 'OC', '.pw', 'USD', 'Dollar', '680', '96940', '^(96940)$', 'pau,sov,en-PW,tox,ja,fil,zh', ' ']\n",
      "http://example.webscraping.com/places/default/view/Pakistan-169 ['803,940 square kilometres', '184,404,791', 'PK', 'Pakistan', 'Islamabad', 'AS', '.pk', 'PKR', 'Rupee', '92', '#####', '^(\\\\d{5})$', 'ur-PK,en-PK,pa,sd,ps,brh', 'CN AF IR IN ']\n",
      "http://example.webscraping.com/places/default/view/Oman-168 ['212,460 square kilometres', '2,967,717', 'OM', 'Oman', 'Muscat', 'AS', '.om', 'OMR', 'Rial', '968', '###', '^(\\\\d{3})$', 'ar-OM,en,bal,ur', 'SA YE AE ']\n",
      "http://example.webscraping.com/places/default/view/Norway-167 ['324,220 square kilometres', '5,009,150', 'NO', 'Norway', 'Oslo', 'EU', '.no', 'NOK', 'Krone', '47', '####', '^(\\\\d{4})$', 'no,nb,nn,se,fi', 'FI RU SE ']\n",
      "http://example.webscraping.com/places/default/view/Northern-Mariana-Islands-166 ['477 square kilometres', '53,883', 'MP', 'Northern Mariana Islands', 'Saipan', 'OC', '.mp', 'USD', 'Dollar', '+1-670', '', '', 'fil,tl,zh,ch-MP,en-MP', ' ']\n",
      "http://example.webscraping.com/places/default/view/North-Korea-165 ['120,540 square kilometres', '22,912,177', 'KP', 'North Korea', 'Pyongyang', 'AS', '.kp', 'KPW', 'Won', '850', '###-###', '^(\\\\d{6})$', 'ko-KP', 'CN KR RU ']\n",
      "http://example.webscraping.com/places/default/view/Norfolk-Island-164 ['34 square kilometres', '1,828', 'NF', 'Norfolk Island', 'Kingston', 'OC', '.nf', 'AUD', 'Dollar', '672', '####', '^(\\\\d{4})$', 'en-NF', ' ']\n",
      "http://example.webscraping.com/places/default/view/Niue-163 ['260 square kilometres', '2,166', 'NU', 'Niue', 'Alofi', 'OC', '.nu', 'NZD', 'Dollar', '683', '', '', 'niu,en-NU', ' ']\n",
      "http://example.webscraping.com/places/default/view/Nigeria-162 ['923,768 square kilometres', '154,000,000', 'NG', 'Nigeria', 'Abuja', 'AF', '.ng', 'NGN', 'Naira', '234', '######', '^(\\\\d{6})$', 'en-NG,ha,yo,ig,ff', 'TD NE BJ CM ']\n",
      "http://example.webscraping.com/places/default/view/Niger-161 ['1,267,000 square kilometres', '15,878,271', 'NE', 'Niger', 'Niamey', 'AF', '.ne', 'XOF', 'Franc', '227', '####', '^(\\\\d{4})$', 'fr-NE,ha,kr,dje', 'TD BJ DZ LY BF NG ML ']\n",
      "http://example.webscraping.com/places/default/view/Nicaragua-160 ['129,494 square kilometres', '5,995,928', 'NI', 'Nicaragua', 'Managua', 'NA', '.ni', 'NIO', 'Cordoba', '505', '###-###-#', '^(\\\\d{7})$', 'es-NI,en', 'CR HN ']\n",
      "http://example.webscraping.com/places/default/view/New-Zealand-159 ['268,680 square kilometres', '4,252,277', 'NZ', 'New Zealand', 'Wellington', 'OC', '.nz', 'NZD', 'Dollar', '64', '####', '^(\\\\d{4})$', 'en-NZ,mi', ' ']\n",
      "http://example.webscraping.com/places/default/view/New-Caledonia-158 ['19,060 square kilometres', '216,494', 'NC', 'New Caledonia', 'Noumea', 'OC', '.nc', 'XPF', 'Franc', '687', '#####', '^(\\\\d{5})$', 'fr-NC', ' ']\n",
      "http://example.webscraping.com/places/default/view/Netherlands-Antilles-157 ['960 square kilometres', '136,197', 'AN', 'Netherlands Antilles', 'Willemstad', 'NA', '.an', 'ANG', 'Guilder', '599', '', '', 'nl-AN,en,es', 'GP ']\n",
      "http://example.webscraping.com/places/default/view/Netherlands-156 ['41,526 square kilometres', '16,645,000', 'NL', 'Netherlands', 'Amsterdam', 'EU', '.nl', 'EUR', 'Euro', '31', '#### @@', '^(\\\\d{4}[A-Z]{2})$', 'nl-NL,fy-NL', 'DE BE ']\n",
      "http://example.webscraping.com/places/default/view/Nepal-155 ['140,800 square kilometres', '28,951,852', 'NP', 'Nepal', 'Kathmandu', 'AS', '.np', 'NPR', 'Rupee', '977', '#####', '^(\\\\d{5})$', 'ne,en', 'CN IN ']\n",
      "http://example.webscraping.com/places/default/view/Nauru-154 ['21 square kilometres', '10,065', 'NR', 'Nauru', 'Yaren', 'OC', '.nr', 'AUD', 'Dollar', '674', '', '', 'na,en-NR', ' ']\n",
      "http://example.webscraping.com/places/default/view/Namibia-153 ['825,418 square kilometres', '2,128,471', 'NA', 'Namibia', 'Windhoek', 'AF', '.na', 'NAD', 'Dollar', '264', '', '', 'en-NA,af,de,hz,naq', 'ZA BW ZM AO ']\n",
      "http://example.webscraping.com/places/default/view/Myanmar-152 ['678,500 square kilometres', '53,414,374', 'MM', 'Myanmar', 'Nay Pyi Taw', 'AS', '.mm', 'MMK', 'Kyat', '95', '#####', '^(\\\\d{5})$', 'my', 'CN LA TH BD IN ']\n",
      "http://example.webscraping.com/places/default/view/Mozambique-151 ['801,590 square kilometres', '22,061,451', 'MZ', 'Mozambique', 'Maputo', 'AF', '.mz', 'MZN', 'Metical', '258', '####', '^(\\\\d{4})$', 'pt-MZ,vmw', 'ZW TZ SZ ZA ZM MW ']\n",
      "http://example.webscraping.com/places/default/view/Morocco-150 ['446,550 square kilometres', '31,627,428', 'MA', 'Morocco', 'Rabat', 'AF', '.ma', 'MAD', 'Dirham', '212', '#####', '^(\\\\d{5})$', 'ar-MA,fr', 'DZ EH ES ']\n",
      "http://example.webscraping.com/places/default/view/Montserrat-149 ['102 square kilometres', '9,341', 'MS', 'Montserrat', 'Plymouth', 'NA', '.ms', 'XCD', 'Dollar', '+1-664', '', '', 'en-MS', ' ']\n",
      "http://example.webscraping.com/places/default/view/Montenegro-148 ['14,026 square kilometres', '666,730', 'ME', 'Montenegro', 'Podgorica', 'EU', '.me', 'EUR', 'Euro', '382', '#####', '^(\\\\d{5})$', 'sr,hu,bs,sq,hr,rom', 'AL HR BA RS XK ']\n",
      "http://example.webscraping.com/places/default/view/Mongolia-147 ['1,565,000 square kilometres', '3,086,918', 'MN', 'Mongolia', 'Ulan Bator', 'AS', '.mn', 'MNT', 'Tugrik', '976', '######', '^(\\\\d{6})$', 'mn,ru', 'CN RU ']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.webscraping.com/places/default/view/Monaco-146 ['1 square kilometres', '32,965', 'MC', 'Monaco', 'Monaco', 'EU', '.mc', 'EUR', 'Euro', '377', '#####', '^(\\\\d{5})$', 'fr-MC,en,it', 'FR ']\n",
      "http://example.webscraping.com/places/default/view/Moldova-145 ['33,843 square kilometres', '4,324,000', 'MD', 'Moldova', 'Chisinau', 'EU', '.md', 'MDL', 'Leu', '373', 'MD-####', '^(?:MD)*(\\\\d{4})$', 'ro,ru,gag,tr', 'RO UA ']\n",
      "http://example.webscraping.com/places/default/view/Micronesia-144 ['702 square kilometres', '107,708', 'FM', 'Micronesia', 'Palikir', 'OC', '.fm', 'USD', 'Dollar', '691', '#####', '^(\\\\d{5})$', 'en-FM,chk,pon,yap,kos,uli,woe,nkr,kpg', ' ']\n",
      "http://example.webscraping.com/places/default/view/Mexico-143 ['1,972,550 square kilometres', '112,468,855', 'MX', 'Mexico', 'Mexico City', 'NA', '.mx', 'MXN', 'Peso', '52', '#####', '^(\\\\d{5})$', 'es-MX', 'GT US BZ ']\n",
      "http://example.webscraping.com/places/default/view/Mayotte-142 ['374 square kilometres', '159,042', 'YT', 'Mayotte', 'Mamoudzou', 'AF', '.yt', 'EUR', 'Euro', '262', '#####', '^(\\\\d{5})$', 'fr-YT', ' ']\n",
      "http://example.webscraping.com/places/default/view/Mauritius-141 ['2,040 square kilometres', '1,294,104', 'MU', 'Mauritius', 'Port Louis', 'AF', '.mu', 'MUR', 'Rupee', '230', '', '', 'en-MU,bho,fr', ' ']\n",
      "http://example.webscraping.com/places/default/view/Mauritania-140 ['1,030,700 square kilometres', '3,205,060', 'MR', 'Mauritania', 'Nouakchott', 'AF', '.mr', 'MRO', 'Ouguiya', '222', '', '', 'ar-MR,fuc,snk,fr,mey,wo', 'SN DZ EH ML ']\n",
      "http://example.webscraping.com/places/default/view/Martinique-139 ['1,100 square kilometres', '432,900', 'MQ', 'Martinique', 'Fort-de-France', 'NA', '.mq', 'EUR', 'Euro', '596', '#####', '^(\\\\d{5})$', 'fr-MQ', ' ']\n",
      "http://example.webscraping.com/places/default/view/Marshall-Islands-138 ['181 square kilometres', '65,859', 'MH', 'Marshall Islands', 'Majuro', 'OC', '.mh', 'USD', 'Dollar', '692', '', '', 'mh,en-MH', ' ']\n",
      "http://example.webscraping.com/places/default/view/Malta-137 ['316 square kilometres', '403,000', 'MT', 'Malta', 'Valletta', 'EU', '.mt', 'EUR', 'Euro', '356', '@@@ ###|@@@ ##', '^([A-Z]{3}\\\\d{2}\\\\d?)$', 'mt,en-MT', ' ']\n",
      "http://example.webscraping.com/places/default/view/Mali-136 ['1,240,000 square kilometres', '13,796,354', 'ML', 'Mali', 'Bamako', 'AF', '.ml', 'XOF', 'Franc', '223', '', '', 'fr-ML,bm', 'SN NE DZ CI GN MR BF ']\n",
      "http://example.webscraping.com/places/default/view/Maldives-135 ['300 square kilometres', '395,650', 'MV', 'Maldives', 'Male', 'AS', '.mv', 'MVR', 'Rufiyaa', '960', '#####', '^(\\\\d{5})$', 'dv,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Malaysia-134 ['329,750 square kilometres', '28,274,729', 'MY', 'Malaysia', 'Kuala Lumpur', 'AS', '.my', 'MYR', 'Ringgit', '60', '#####', '^(\\\\d{5})$', 'ms-MY,en,zh,ta,te,ml,pa,th', 'BN TH ID ']\n",
      "http://example.webscraping.com/places/default/view/Malawi-133 ['118,480 square kilometres', '15,447,500', 'MW', 'Malawi', 'Lilongwe', 'AF', '.mw', 'MWK', 'Kwacha', '265', '', '', 'ny,yao,tum,swk', 'TZ MZ ZM ']\n",
      "http://example.webscraping.com/places/default/view/Madagascar-132 ['587,040 square kilometres', '21,281,844', 'MG', 'Madagascar', 'Antananarivo', 'AF', '.mg', 'MGA', 'Ariary', '261', '###', '^(\\\\d{3})$', 'fr-MG,mg', ' ']\n",
      "http://example.webscraping.com/places/default/view/Macedonia-131 ['25,333 square kilometres', '2,062,294', 'MK', 'Macedonia', 'Skopje', 'EU', '.mk', 'MKD', 'Denar', '389', '####', '^(\\\\d{4})$', 'mk,sq,tr,rmm,sr', 'AL GR CS BG RS XK ']\n",
      "http://example.webscraping.com/places/default/view/Macao-130 ['254 square kilometres', '449,198', 'MO', 'Macao', 'Macao', 'AS', '.mo', 'MOP', 'Pataca', '853', '', '', 'zh,zh-MO,pt', ' ']\n",
      "http://example.webscraping.com/places/default/view/Luxembourg-129 ['2,586 square kilometres', '497,538', 'LU', 'Luxembourg', 'Luxembourg', 'EU', '.lu', 'EUR', 'Euro', '352', 'L-####', '^(\\\\d{4})$', 'lb,de-LU,fr-LU', 'DE BE FR ']\n",
      "http://example.webscraping.com/places/default/view/Lithuania-128 ['65,200 square kilometres', '3,565,000', 'LT', 'Lithuania', 'Vilnius', 'EU', '.lt', 'LTL', 'Litas', '370', 'LT-#####', '^(?:LT)*(\\\\d{5})$', 'lt,ru,pl', 'PL BY RU LV ']\n",
      "http://example.webscraping.com/places/default/view/Liechtenstein-127 ['160 square kilometres', '35,000', 'LI', 'Liechtenstein', 'Vaduz', 'EU', '.li', 'CHF', 'Franc', '423', '####', '^(\\\\d{4})$', 'de-LI', 'CH AT ']\n",
      "http://example.webscraping.com/places/default/view/Libya-126 ['1,759,540 square kilometres', '6,461,454', 'LY', 'Libya', 'Tripolis', 'AF', '.ly', 'LYD', 'Dinar', '218', '', '', 'ar-LY,it,en', 'TD NE DZ SD TN EG ']\n",
      "http://example.webscraping.com/places/default/view/Liberia-125 ['111,370 square kilometres', '3,685,076', 'LR', 'Liberia', 'Monrovia', 'AF', '.lr', 'LRD', 'Dollar', '231', '####', '^(\\\\d{4})$', 'en-LR', 'SL CI GN ']\n",
      "http://example.webscraping.com/places/default/view/Lesotho-124 ['30,355 square kilometres', '1,919,552', 'LS', 'Lesotho', 'Maseru', 'AF', '.ls', 'LSL', 'Loti', '266', '###', '^(\\\\d{3})$', 'en-LS,st,zu,xh', 'ZA ']\n",
      "http://example.webscraping.com/places/default/view/Lebanon-123 ['10,400 square kilometres', '4,125,247', 'LB', 'Lebanon', 'Beirut', 'AS', '.lb', 'LBP', 'Pound', '961', '#### ####|####', '^(\\\\d{4}(\\\\d{4})?)$', 'ar-LB,fr-LB,en,hy', 'SY IL ']\n",
      "http://example.webscraping.com/places/default/view/Latvia-122 ['64,589 square kilometres', '2,217,969', 'LV', 'Latvia', 'Riga', 'EU', '.lv', 'EUR', 'Euro', '371', 'LV-####', '^(?:LV)*(\\\\d{4})$', 'lv,ru,lt', 'LT EE BY RU ']\n",
      "http://example.webscraping.com/places/default/view/Laos-121 ['236,800 square kilometres', '6,368,162', 'LA', 'Laos', 'Vientiane', 'AS', '.la', 'LAK', 'Kip', '856', '#####', '^(\\\\d{5})$', 'lo,fr,en', 'CN MM KH TH VN ']\n",
      "http://example.webscraping.com/places/default/view/Kyrgyzstan-120 ['198,500 square kilometres', '5,508,626', 'KG', 'Kyrgyzstan', 'Bishkek', 'AS', '.kg', 'KGS', 'Som', '996', '######', '^(\\\\d{6})$', 'ky,uz,ru', 'CN TJ UZ KZ ']\n",
      "http://example.webscraping.com/places/default/view/Kuwait-119 ['17,820 square kilometres', '2,789,132', 'KW', 'Kuwait', 'Kuwait City', 'AS', '.kw', 'KWD', 'Dinar', '965', '#####', '^(\\\\d{5})$', 'ar-KW,en', 'SA IQ ']\n",
      "http://example.webscraping.com/places/default/view/Kosovo-118 ['10,908 square kilometres', '1,800,000', 'XK', 'Kosovo', 'Pristina', 'EU', '', 'EUR', 'Euro', '', '', '', 'sq,sr', 'RS AL MK ME ']\n",
      "http://example.webscraping.com/places/default/view/Kiribati-117 ['811 square kilometres', '92,533', 'KI', 'Kiribati', 'Tarawa', 'OC', '.ki', 'AUD', 'Dollar', '686', '', '', 'en-KI,gil', ' ']\n",
      "http://example.webscraping.com/places/default/view/Kenya-116 ['582,650 square kilometres', '40,046,566', 'KE', 'Kenya', 'Nairobi', 'AF', '.ke', 'KES', 'Shilling', '254', '#####', '^(\\\\d{5})$', 'en-KE,sw-KE', 'ET TZ SS SO UG ']\n",
      "http://example.webscraping.com/places/default/view/Kazakhstan-115 ['2,717,300 square kilometres', '15,340,000', 'KZ', 'Kazakhstan', 'Astana', 'AS', '.kz', 'KZT', 'Tenge', '7', '######', '^(\\\\d{6})$', 'kk,ru', 'TM CN KG UZ RU ']\n",
      "http://example.webscraping.com/places/default/view/Jordan-114 ['92,300 square kilometres', '6,407,085', 'JO', 'Jordan', 'Amman', 'AS', '.jo', 'JOD', 'Dinar', '962', '#####', '^(\\\\d{5})$', 'ar-JO,en', 'SY SA IQ IL PS ']\n",
      "http://example.webscraping.com/places/default/view/Jersey-113 ['116 square kilometres', '90,812', 'JE', 'Jersey', 'Saint Helier', 'EU', '.je', 'GBP', 'Pound', '+44-1534', '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA', '^(([A-Z]\\\\d{2}[A-Z]{2})|([A-Z]\\\\d{3}[A-Z]{2})|([A-Z]{2}\\\\d{2}[A-Z]{2})|([A-Z]{2}\\\\d{3}[A-Z]{2})|([A-Z]\\\\d[A-Z]\\\\d[A-Z]{2})|([A-Z]{2}\\\\d[A-Z]\\\\d[A-Z]{2})|(GIR0AA))$', 'en,pt', ' ']\n",
      "http://example.webscraping.com/places/default/view/Japan-112 ['377,835 square kilometres', '127,288,000', 'JP', 'Japan', 'Tokyo', 'AS', '.jp', 'JPY', 'Yen', '81', '###-####', '^(\\\\d{7})$', 'ja', ' ']\n",
      "http://example.webscraping.com/places/default/view/Jamaica-111 ['10,991 square kilometres', '2,847,232', 'JM', 'Jamaica', 'Kingston', 'NA', '.jm', 'JMD', 'Dollar', '+1-876', '', '', 'en-JM', ' ']\n",
      "http://example.webscraping.com/places/default/view/Ivory-Coast-110 ['322,460 square kilometres', '21,058,798', 'CI', 'Ivory Coast', 'Yamoussoukro', 'AF', '.ci', 'XOF', 'Franc', '225', '', '', 'fr-CI', 'LR GH GN BF ML ']\n",
      "http://example.webscraping.com/places/default/view/Italy-109 ['301,230 square kilometres', '60,340,328', 'IT', 'Italy', 'Rome', 'EU', '.it', 'EUR', 'Euro', '39', '#####', '^(\\\\d{5})$', 'it-IT,de-IT,fr-IT,sc,ca,co,sl', 'CH VA SI SM FR AT ']\n",
      "http://example.webscraping.com/places/default/view/Israel-108 ['20,770 square kilometres', '7,353,985', 'IL', 'Israel', 'Jerusalem', 'AS', '.il', 'ILS', 'Shekel', '972', '#####', '^(\\\\d{5})$', 'he,ar-IL,en-IL,', 'SY JO LB EG PS ']\n",
      "http://example.webscraping.com/places/default/view/Isle-of-Man-107 ['572 square kilometres', '75,049', 'IM', 'Isle of Man', 'Douglas, Isle of Man', 'EU', '.im', 'GBP', 'Pound', '+44-1624', '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA', '^(([A-Z]\\\\d{2}[A-Z]{2})|([A-Z]\\\\d{3}[A-Z]{2})|([A-Z]{2}\\\\d{2}[A-Z]{2})|([A-Z]{2}\\\\d{3}[A-Z]{2})|([A-Z]\\\\d[A-Z]\\\\d[A-Z]{2})|([A-Z]{2}\\\\d[A-Z]\\\\d[A-Z]{2})|(GIR0AA))$', 'en,gv', ' ']\n",
      "http://example.webscraping.com/places/default/view/Ireland-106 ['70,280 square kilometres', '4,622,917', 'IE', 'Ireland', 'Dublin', 'EU', '.ie', 'EUR', 'Euro', '353', '', '', 'en-IE,ga-IE', 'GB ']\n",
      "http://example.webscraping.com/places/default/view/Iraq-105 ['437,072 square kilometres', '29,671,605', 'IQ', 'Iraq', 'Baghdad', 'AS', '.iq', 'IQD', 'Dinar', '964', '#####', '^(\\\\d{5})$', 'ar-IQ,ku,hy', 'SY SA IR JO TR KW ']\n",
      "http://example.webscraping.com/places/default/view/Iran-104 ['1,648,000 square kilometres', '76,923,300', 'IR', 'Iran', 'Tehran', 'AS', '.ir', 'IRR', 'Rial', '98', '##########', '^(\\\\d{10})$', 'fa-IR,ku', 'TM AF IQ AM PK AZ TR ']\n",
      "http://example.webscraping.com/places/default/view/Indonesia-103 ['1,919,440 square kilometres', '242,968,342', 'ID', 'Indonesia', 'Jakarta', 'AS', '.id', 'IDR', 'Rupiah', '62', '#####', '^(\\\\d{5})$', 'id,en,nl,jv', 'PG TL MY ']\n",
      "http://example.webscraping.com/places/default/view/India-102 ['3,287,590 square kilometres', '1,173,108,018', 'IN', 'India', 'New Delhi', 'AS', '.in', 'INR', 'Rupee', '91', '######', '^(\\\\d{6})$', 'en-IN,hi,bn,te,mr,ta,ur,gu,kn,ml,or,pa,as,bh,sat,ks,ne,sd,kok,doi,mni,sit,sa,fr,lus,inc', 'CN NP MM BT PK BD ']\n",
      "http://example.webscraping.com/places/default/view/Iceland-101 ['103,000 square kilometres', '308,910', 'IS', 'Iceland', 'Reykjavik', 'EU', '.is', 'ISK', 'Krona', '354', '###', '^(\\\\d{3})$', 'is,en,de,da,sv,no', ' ']\n",
      "http://example.webscraping.com/places/default/view/Hungary-100 ['93,030 square kilometres', '9,982,000', 'HU', 'Hungary', 'Budapest', 'EU', '.hu', 'HUF', 'Forint', '36', '####', '^(\\\\d{4})$', 'hu-HU', 'SK SI RO UA CS HR AT RS ']\n",
      "http://example.webscraping.com/places/default/view/Hong-Kong-99 ['1,092 square kilometres', '6,898,686', 'HK', 'Hong Kong', 'Hong Kong', 'AS', '.hk', 'HKD', 'Dollar', '852', '', '', 'zh-HK,yue,zh,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Honduras-98 ['112,090 square kilometres', '7,989,415', 'HN', 'Honduras', 'Tegucigalpa', 'NA', '.hn', 'HNL', 'Lempira', '504', '@@####', '^([A-Z]{2}\\\\d{4})$', 'es-HN', 'GT NI SV ']\n",
      "http://example.webscraping.com/places/default/view/Heard-Island-and-McDonald-Islands-97 ['412 square kilometres', '0', 'HM', 'Heard Island and McDonald Islands', '', 'AN', '.hm', 'AUD', 'Dollar', '', '', '', '', ' ']\n",
      "http://example.webscraping.com/places/default/view/Haiti-96 ['27,750 square kilometres', '9,648,924', 'HT', 'Haiti', 'Port-au-Prince', 'NA', '.ht', 'HTG', 'Gourde', '509', 'HT####', '^(?:HT)*(\\\\d{4})$', 'ht,fr-HT', 'DO ']\n",
      "http://example.webscraping.com/places/default/view/Guyana-95 ['214,970 square kilometres', '748,486', 'GY', 'Guyana', 'Georgetown', 'SA', '.gy', 'GYD', 'Dollar', '592', '', '', 'en-GY', 'SR BR VE ']\n",
      "http://example.webscraping.com/places/default/view/Guinea-Bissau-94 ['36,120 square kilometres', '1,565,126', 'GW', 'Guinea-Bissau', 'Bissau', 'AF', '.gw', 'XOF', 'Franc', '245', '####', '^(\\\\d{4})$', 'pt-GW,pov', 'SN GN ']\n",
      "http://example.webscraping.com/places/default/view/Guinea-93 ['245,857 square kilometres', '10,324,025', 'GN', 'Guinea', 'Conakry', 'AF', '.gn', 'GNF', 'Franc', '224', '', '', 'fr-GN', 'LR SN SL CI GW ML ']\n",
      "http://example.webscraping.com/places/default/view/Guernsey-92 ['78 square kilometres', '65,228', 'GG', 'Guernsey', 'St Peter Port', 'EU', '.gg', 'GBP', 'Pound', '+44-1481', '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA', '^(([A-Z]\\\\d{2}[A-Z]{2})|([A-Z]\\\\d{3}[A-Z]{2})|([A-Z]{2}\\\\d{2}[A-Z]{2})|([A-Z]{2}\\\\d{3}[A-Z]{2})|([A-Z]\\\\d[A-Z]\\\\d[A-Z]{2})|([A-Z]{2}\\\\d[A-Z]\\\\d[A-Z]{2})|(GIR0AA))$', 'en,fr', ' ']\n",
      "http://example.webscraping.com/places/default/view/Guatemala-91 ['108,890 square kilometres', '13,550,440', 'GT', 'Guatemala', 'Guatemala City', 'NA', '.gt', 'GTQ', 'Quetzal', '502', '#####', '^(\\\\d{5})$', 'es-GT', 'MX HN BZ SV ']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.webscraping.com/places/default/view/Guam-90 ['549 square kilometres', '159,358', 'GU', 'Guam', 'Hagatna', 'OC', '.gu', 'USD', 'Dollar', '+1-671', '969##', '^(969\\\\d{2})$', 'en-GU,ch-GU', ' ']\n",
      "http://example.webscraping.com/places/default/view/Guadeloupe-89 ['1,780 square kilometres', '443,000', 'GP', 'Guadeloupe', 'Basse-Terre', 'NA', '.gp', 'EUR', 'Euro', '590', '#####', '^((97|98)\\\\d{3})$', 'fr-GP', 'AN ']\n",
      "http://example.webscraping.com/places/default/view/Grenada-88 ['344 square kilometres', '107,818', 'GD', 'Grenada', \"St. George's\", 'NA', '.gd', 'XCD', 'Dollar', '+1-473', '', '', 'en-GD', ' ']\n",
      "http://example.webscraping.com/places/default/view/Greenland-87 ['2,166,086 square kilometres', '56,375', 'GL', 'Greenland', 'Nuuk', 'NA', '.gl', 'DKK', 'Krone', '299', '####', '^(\\\\d{4})$', 'kl,da-GL,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Greece-86 ['131,940 square kilometres', '11,000,000', 'GR', 'Greece', 'Athens', 'EU', '.gr', 'EUR', 'Euro', '30', '### ##', '^(\\\\d{5})$', 'el-GR,en,fr', 'AL MK TR BG ']\n",
      "http://example.webscraping.com/places/default/view/Gibraltar-85 ['6 square kilometres', '27,884', 'GI', 'Gibraltar', 'Gibraltar', 'EU', '.gi', 'GIP', 'Pound', '350', '', '', 'en-GI,es,it,pt', 'ES ']\n",
      "http://example.webscraping.com/places/default/view/Ghana-84 ['239,460 square kilometres', '24,339,838', 'GH', 'Ghana', 'Accra', 'AF', '.gh', 'GHS', 'Cedi', '233', '', '', 'en-GH,ak,ee,tw', 'CI TG BF ']\n",
      "http://example.webscraping.com/places/default/view/Germany-83 ['357,021 square kilometres', '81,802,257', 'DE', 'Germany', 'Berlin', 'EU', '.de', 'EUR', 'Euro', '49', '#####', '^(\\\\d{5})$', 'de', 'CH PL NL DK BE CZ LU FR AT ']\n",
      "http://example.webscraping.com/places/default/view/Georgia-82 ['69,700 square kilometres', '4,630,000', 'GE', 'Georgia', 'Tbilisi', 'AS', '.ge', 'GEL', 'Lari', '995', '####', '^(\\\\d{4})$', 'ka,ru,hy,az', 'AM AZ TR RU ']\n",
      "http://example.webscraping.com/places/default/view/Gambia-81 ['11,300 square kilometres', '1,593,256', 'GM', 'Gambia', 'Banjul', 'AF', '.gm', 'GMD', 'Dalasi', '220', '', '', 'en-GM,mnk,wof,wo,ff', 'SN ']\n",
      "http://example.webscraping.com/places/default/view/Gabon-80 ['267,667 square kilometres', '1,545,255', 'GA', 'Gabon', 'Libreville', 'AF', '.ga', 'XAF', 'Franc', '241', '', '', 'fr-GA', 'CM GQ CG ']\n",
      "http://example.webscraping.com/places/default/view/French-Southern-Territories-79 ['7,829 square kilometres', '140', 'TF', 'French Southern Territories', 'Port-aux-Francais', 'AN', '.tf', 'EUR', 'Euro', '', '', '', 'fr', ' ']\n",
      "http://example.webscraping.com/places/default/view/French-Polynesia-78 ['4,167 square kilometres', '270,485', 'PF', 'French Polynesia', 'Papeete', 'OC', '.pf', 'XPF', 'Franc', '689', '#####', '^((97|98)7\\\\d{2})$', 'fr-PF,ty', ' ']\n",
      "http://example.webscraping.com/places/default/view/French-Guiana-77 ['91,000 square kilometres', '195,506', 'GF', 'French Guiana', 'Cayenne', 'SA', '.gf', 'EUR', 'Euro', '594', '#####', '^((97|98)3\\\\d{2})$', 'fr-GF', 'SR BR ']\n",
      "http://example.webscraping.com/places/default/view/France-76 ['547,030 square kilometres', '64,768,389', 'FR', 'France', 'Paris', 'EU', '.fr', 'EUR', 'Euro', '33', '#####', '^(\\\\d{5})$', 'fr-FR,frp,br,co,ca,eu,oc', 'CH DE BE LU IT AD MC ES ']\n",
      "http://example.webscraping.com/places/default/view/Finland-75 ['337,030 square kilometres', '5,244,000', 'FI', 'Finland', 'Helsinki', 'EU', '.fi', 'EUR', 'Euro', '358', '#####', '^(?:FI)*(\\\\d{5})$', 'fi-FI,sv-FI,smn', 'NO RU SE ']\n",
      "http://example.webscraping.com/places/default/view/Fiji-74 ['18,270 square kilometres', '875,983', 'FJ', 'Fiji', 'Suva', 'OC', '.fj', 'FJD', 'Dollar', '679', '', '', 'en-FJ,fj', ' ']\n",
      "http://example.webscraping.com/places/default/view/Faroe-Islands-73 ['1,399 square kilometres', '48,228', 'FO', 'Faroe Islands', 'Torshavn', 'EU', '.fo', 'DKK', 'Krone', '298', 'FO-###', '^(?:FO)*(\\\\d{3})$', 'fo,da-FO', ' ']\n",
      "http://example.webscraping.com/places/default/view/Falkland-Islands-72 ['12,173 square kilometres', '2,638', 'FK', 'Falkland Islands', 'Stanley', 'SA', '.fk', 'FKP', 'Pound', '500', '', '', 'en-FK', ' ']\n",
      "http://example.webscraping.com/places/default/view/Ethiopia-71 ['1,127,127 square kilometres', '88,013,491', 'ET', 'Ethiopia', 'Addis Ababa', 'AF', '.et', 'ETB', 'Birr', '251', '####', '^(\\\\d{4})$', 'am,en-ET,om-ET,ti-ET,so-ET,sid', 'ER KE SD SS SO DJ ']\n",
      "http://example.webscraping.com/places/default/view/Estonia-70 ['45,226 square kilometres', '1,291,170', 'EE', 'Estonia', 'Tallinn', 'EU', '.ee', 'EUR', 'Euro', '372', '#####', '^(\\\\d{5})$', 'et,ru', 'RU LV ']\n",
      "http://example.webscraping.com/places/default/view/Eritrea-69 ['121,320 square kilometres', '5,792,984', 'ER', 'Eritrea', 'Asmara', 'AF', '.er', 'ERN', 'Nakfa', '291', '', '', 'aa-ER,ar,tig,kun,ti-ER', 'ET SD DJ ']\n",
      "http://example.webscraping.com/places/default/view/Equatorial-Guinea-68 ['28,051 square kilometres', '1,014,999', 'GQ', 'Equatorial Guinea', 'Malabo', 'AF', '.gq', 'XAF', 'Franc', '240', '', '', 'es-GQ,fr', 'GA CM ']\n",
      "http://example.webscraping.com/places/default/view/El-Salvador-67 ['21,040 square kilometres', '6,052,064', 'SV', 'El Salvador', 'San Salvador', 'NA', '.sv', 'USD', 'Dollar', '503', 'CP ####', '^(?:CP)*(\\\\d{4})$', 'es-SV', 'GT HN ']\n",
      "http://example.webscraping.com/places/default/view/Egypt-66 ['1,001,450 square kilometres', '80,471,869', 'EG', 'Egypt', 'Cairo', 'AF', '.eg', 'EGP', 'Pound', '20', '#####', '^(\\\\d{5})$', 'ar-EG,en,fr', 'LY SD IL ']\n",
      "http://example.webscraping.com/places/default/view/Ecuador-65 ['283,560 square kilometres', '14,790,608', 'EC', 'Ecuador', 'Quito', 'SA', '.ec', 'USD', 'Dollar', '593', '@####@', '^([a-zA-Z]\\\\d{4}[a-zA-Z])$', 'es-EC', 'PE CO ']\n",
      "http://example.webscraping.com/places/default/view/East-Timor-64 ['15,007 square kilometres', '1,154,625', 'TL', 'East Timor', 'Dili', 'OC', '.tl', 'USD', 'Dollar', '670', '', '', 'tet,pt-TL,id,en', 'ID ']\n",
      "http://example.webscraping.com/places/default/view/Dominican-Republic-63 ['48,730 square kilometres', '9,823,821', 'DO', 'Dominican Republic', 'Santo Domingo', 'NA', '.do', 'DOP', 'Peso', '+1-809 and 1-829', '#####', '^(\\\\d{5})$', 'es-DO', 'HT ']\n",
      "http://example.webscraping.com/places/default/view/Dominica-62 ['754 square kilometres', '72,813', 'DM', 'Dominica', 'Roseau', 'NA', '.dm', 'XCD', 'Dollar', '+1-767', '', '', 'en-DM', ' ']\n",
      "http://example.webscraping.com/places/default/view/Djibouti-61 ['23,000 square kilometres', '740,528', 'DJ', 'Djibouti', 'Djibouti', 'AF', '.dj', 'DJF', 'Franc', '253', '', '', 'fr-DJ,ar,so-DJ,aa', 'ER ET SO ']\n",
      "http://example.webscraping.com/places/default/view/Denmark-60 ['43,094 square kilometres', '5,484,000', 'DK', 'Denmark', 'Copenhagen', 'EU', '.dk', 'DKK', 'Krone', '45', '####', '^(\\\\d{4})$', 'da-DK,en,fo,de-DK', 'DE ']\n",
      "http://example.webscraping.com/places/default/view/Democratic-Republic-of-the-Congo-59 ['2,345,410 square kilometres', '70,916,439', 'CD', 'Democratic Republic of the Congo', 'Kinshasa', 'AF', '.cd', 'CDF', 'Franc', '243', '', '', 'fr-CD,ln,kg', 'TZ CF SS RW ZM BI UG CG AO ']\n",
      "http://example.webscraping.com/places/default/view/Czech-Republic-58 ['78,866 square kilometres', '10,476,000', 'CZ', 'Czech Republic', 'Prague', 'EU', '.cz', 'CZK', 'Koruna', '420', '### ##', '^(\\\\d{5})$', 'cs,sk', 'PL DE SK AT ']\n",
      "http://example.webscraping.com/places/default/view/Cyprus-57 ['9,250 square kilometres', '1,102,677', 'CY', 'Cyprus', 'Nicosia', 'EU', '.cy', 'EUR', 'Euro', '357', '####', '^(\\\\d{4})$', 'el-CY,tr-CY,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Curacao-56 ['444 square kilometres', '141,766', 'CW', 'Curacao', 'Willemstad', 'NA', '.cw', 'ANG', 'Guilder', '599', '', '', 'nl,pap', ' ']\n",
      "http://example.webscraping.com/places/default/view/Cuba-55 ['110,860 square kilometres', '11,423,000', 'CU', 'Cuba', 'Havana', 'NA', '.cu', 'CUP', 'Peso', '53', 'CP #####', '^(?:CP)*(\\\\d{5})$', 'es-CU', 'US ']\n",
      "http://example.webscraping.com/places/default/view/Croatia-54 ['56,542 square kilometres', '4,491,000', 'HR', 'Croatia', 'Zagreb', 'EU', '.hr', 'HRK', 'Kuna', '385', '#####', '^(?:HR)*(\\\\d{5})$', 'hr-HR,sr', 'HU SI CS BA ME RS ']\n",
      "http://example.webscraping.com/places/default/view/Costa-Rica-53 ['51,100 square kilometres', '4,516,220', 'CR', 'Costa Rica', 'San Jose', 'NA', '.cr', 'CRC', 'Colon', '506', '####', '^(\\\\d{4})$', 'es-CR,en', 'PA NI ']\n",
      "http://example.webscraping.com/places/default/view/Cook-Islands-52 ['240 square kilometres', '21,388', 'CK', 'Cook Islands', 'Avarua', 'OC', '.ck', 'NZD', 'Dollar', '682', '', '', 'en-CK,mi', ' ']\n",
      "http://example.webscraping.com/places/default/view/Comoros-51 ['2,170 square kilometres', '773,407', 'KM', 'Comoros', 'Moroni', 'AF', '.km', 'KMF', 'Franc', '269', '', '', 'ar,fr-KM', ' ']\n",
      "http://example.webscraping.com/places/default/view/Colombia-50 ['1,138,910 square kilometres', '44,205,293', 'CO', 'Colombia', 'Bogota', 'SA', '.co', 'COP', 'Peso', '57', '', '', 'es-CO', 'EC PE PA BR VE ']\n",
      "http://example.webscraping.com/places/default/view/Cocos-Islands-49 ['14 square kilometres', '628', 'CC', 'Cocos Islands', 'West Island', 'AS', '.cc', 'AUD', 'Dollar', '61', '', '', 'ms-CC,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Christmas-Island-48 ['135 square kilometres', '1,500', 'CX', 'Christmas Island', 'Flying Fish Cove', 'AS', '.cx', 'AUD', 'Dollar', '61', '####', '^(\\\\d{4})$', 'en,zh,ms-CC', ' ']\n",
      "http://example.webscraping.com/places/default/view/China-47 ['9,596,960 square kilometres', '1,330,044,000', 'CN', 'China', 'Beijing', 'AS', '.cn', 'CNY', 'Yuan Renminbi', '86', '######', '^(\\\\d{6})$', 'zh-CN,yue,wuu,dta,ug,za', 'LA BT TJ KZ MN AF NP MM KG PK KP RU VN IN ']\n",
      "http://example.webscraping.com/places/default/view/Chile-46 ['756,950 square kilometres', '16,746,491', 'CL', 'Chile', 'Santiago', 'SA', '.cl', 'CLP', 'Peso', '56', '#######', '^(\\\\d{7})$', 'es-CL', 'PE BO AR ']\n",
      "http://example.webscraping.com/places/default/view/Chad-45 ['1,284,000 square kilometres', '10,543,464', 'TD', 'Chad', \"N'Djamena\", 'AF', '.td', 'XAF', 'Franc', '235', '', '', 'fr-TD,ar-TD,sre', 'NE LY CF SD CM NG ']\n",
      "http://example.webscraping.com/places/default/view/Central-African-Republic-44 ['622,984 square kilometres', '4,844,927', 'CF', 'Central African Republic', 'Bangui', 'AF', '.cf', 'XAF', 'Franc', '236', '', '', 'fr-CF,sg,ln,kg', 'TD SD CD SS CM CG ']\n",
      "http://example.webscraping.com/places/default/view/Cayman-Islands-43 ['262 square kilometres', '44,270', 'KY', 'Cayman Islands', 'George Town', 'NA', '.ky', 'KYD', 'Dollar', '+1-345', '', '', 'en-KY', ' ']\n",
      "http://example.webscraping.com/places/default/view/Cape-Verde-42 ['4,033 square kilometres', '508,659', 'CV', 'Cape Verde', 'Praia', 'AF', '.cv', 'CVE', 'Escudo', '238', '####', '^(\\\\d{4})$', 'pt-CV', ' ']\n",
      "http://example.webscraping.com/places/default/view/Canada-41 ['9,984,670 square kilometres', '33,679,000', 'CA', 'Canada', 'Ottawa', 'NA', '.ca', 'CAD', 'Dollar', '1', '@#@ #@#', '^([ABCEGHJKLMNPRSTVXY]\\\\d[ABCEGHJKLMNPRSTVWXYZ]) ?(\\\\d[ABCEGHJKLMNPRSTVWXYZ]\\\\d)$', 'en-CA,fr-CA,iu', 'US ']\n",
      "http://example.webscraping.com/places/default/view/Cameroon-40 ['475,440 square kilometres', '19,294,149', 'CM', 'Cameroon', 'Yaounde', 'AF', '.cm', 'XAF', 'Franc', '237', '', '', 'en-CM,fr-CM', 'TD CF GA GQ CG NG ']\n",
      "http://example.webscraping.com/places/default/view/Cambodia-39 ['181,040 square kilometres', '14,453,680', 'KH', 'Cambodia', 'Phnom Penh', 'AS', '.kh', 'KHR', 'Riels', '855', '#####', '^(\\\\d{5})$', 'km,fr,en', 'LA TH VN ']\n",
      "http://example.webscraping.com/places/default/view/Burundi-38 ['27,830 square kilometres', '9,863,117', 'BI', 'Burundi', 'Bujumbura', 'AF', '.bi', 'BIF', 'Franc', '257', '', '', 'fr-BI,rn', 'TZ CD RW ']\n",
      "http://example.webscraping.com/places/default/view/Burkina-Faso-37 ['274,200 square kilometres', '16,241,811', 'BF', 'Burkina Faso', 'Ouagadougou', 'AF', '.bf', 'XOF', 'Franc', '226', '', '', 'fr-BF', 'NE BJ GH CI TG ML ']\n",
      "http://example.webscraping.com/places/default/view/Bulgaria-36 ['110,910 square kilometres', '7,148,785', 'BG', 'Bulgaria', 'Sofia', 'EU', '.bg', 'BGN', 'Lev', '359', '####', '^(\\\\d{4})$', 'bg,tr-BG', 'MK GR RO CS TR RS ']\n",
      "http://example.webscraping.com/places/default/view/Brunei-35 ['5,770 square kilometres', '395,027', 'BN', 'Brunei', 'Bandar Seri Begawan', 'AS', '.bn', 'BND', 'Dollar', '673', '@@####', '^([A-Z]{2}\\\\d{4})$', 'ms-BN,en-BN', 'MY ']\n",
      "http://example.webscraping.com/places/default/view/British-Virgin-Islands-34 ['153 square kilometres', '21,730', 'VG', 'British Virgin Islands', 'Road Town', 'NA', '.vg', 'USD', 'Dollar', '+1-284', '', '', 'en-VG', ' ']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.webscraping.com/places/default/view/British-Indian-Ocean-Territory-33 ['60 square kilometres', '4,000', 'IO', 'British Indian Ocean Territory', 'Diego Garcia', 'AS', '.io', 'USD', 'Dollar', '246', '', '', 'en-IO', ' ']\n",
      "http://example.webscraping.com/places/default/view/Brazil-32 ['8,511,965 square kilometres', '201,103,330', 'BR', 'Brazil', 'Brasilia', 'SA', '.br', 'BRL', 'Real', '55', '#####-###', '^(\\\\d{8})$', 'pt-BR,es,en,fr', 'SR PE BO UY GY PY GF VE CO AR ']\n",
      "http://example.webscraping.com/places/default/view/Bouvet-Island-31 ['49 square kilometres', '0', 'BV', 'Bouvet Island', '', 'AN', '.bv', 'NOK', 'Krone', '', '', '', '', ' ']\n",
      "http://example.webscraping.com/places/default/view/Botswana-30 ['600,370 square kilometres', '2,029,307', 'BW', 'Botswana', 'Gaborone', 'AF', '.bw', 'BWP', 'Pula', '267', '', '', 'en-BW,tn-BW', 'ZW ZA NA ']\n",
      "http://example.webscraping.com/places/default/view/Bosnia-and-Herzegovina-29 ['51,129 square kilometres', '4,590,000', 'BA', 'Bosnia and Herzegovina', 'Sarajevo', 'EU', '.ba', 'BAM', 'Marka', '387', '#####', '^(\\\\d{5})$', 'bs,hr-BA,sr-BA', 'CS HR ME RS ']\n",
      "http://example.webscraping.com/places/default/view/Bonaire-Saint-Eustatius-and-Saba-28 ['328 square kilometres', '18,012', 'BQ', 'Bonaire, Saint Eustatius and Saba', '', 'NA', '.bq', 'USD', 'Dollar', '599', '', '', 'nl,pap,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Bolivia-27 ['1,098,580 square kilometres', '9,947,418', 'BO', 'Bolivia', 'Sucre', 'SA', '.bo', 'BOB', 'Boliviano', '591', '', '', 'es-BO,qu,ay', 'PE CL PY BR AR ']\n",
      "http://example.webscraping.com/places/default/view/Bhutan-26 ['47,000 square kilometres', '699,847', 'BT', 'Bhutan', 'Thimphu', 'AS', '.bt', 'BTN', 'Ngultrum', '975', '', '', 'dz', 'CN IN ']\n",
      "http://example.webscraping.com/places/default/view/Bermuda-25 ['53 square kilometres', '65,365', 'BM', 'Bermuda', 'Hamilton', 'NA', '.bm', 'BMD', 'Dollar', '+1-441', '@@ ##', '^([A-Z]{2}\\\\d{2})$', 'en-BM,pt', ' ']\n",
      "http://example.webscraping.com/places/default/view/Benin-24 ['112,620 square kilometres', '9,056,010', 'BJ', 'Benin', 'Porto-Novo', 'AF', '.bj', 'XOF', 'Franc', '229', '', '', 'fr-BJ', 'NE TG BF NG ']\n",
      "http://example.webscraping.com/places/default/view/Belize-23 ['22,966 square kilometres', '314,522', 'BZ', 'Belize', 'Belmopan', 'NA', '.bz', 'BZD', 'Dollar', '501', '', '', 'en-BZ,es', 'GT MX ']\n",
      "http://example.webscraping.com/places/default/view/Belgium-22 ['30,510 square kilometres', '10,403,000', 'BE', 'Belgium', 'Brussels', 'EU', '.be', 'EUR', 'Euro', '32', '####', '^(\\\\d{4})$', 'nl-BE,fr-BE,de-BE', 'DE NL LU FR ']\n",
      "http://example.webscraping.com/places/default/view/Belarus-21 ['207,600 square kilometres', '9,685,000', 'BY', 'Belarus', 'Minsk', 'EU', '.by', 'BYR', 'Ruble', '375', '######', '^(\\\\d{6})$', 'be,ru', 'PL LT UA RU LV ']\n",
      "http://example.webscraping.com/places/default/view/Barbados-20 ['431 square kilometres', '285,653', 'BB', 'Barbados', 'Bridgetown', 'NA', '.bb', 'BBD', 'Dollar', '+1-246', 'BB#####', '^(?:BB)*(\\\\d{5})$', 'en-BB', ' ']\n",
      "http://example.webscraping.com/places/default/view/Bangladesh-19 ['144,000 square kilometres', '156,118,464', 'BD', 'Bangladesh', 'Dhaka', 'AS', '.bd', 'BDT', 'Taka', '880', '####', '^(\\\\d{4})$', 'bn-BD,en', 'MM IN ']\n",
      "http://example.webscraping.com/places/default/view/Bahrain-18 ['665 square kilometres', '738,004', 'BH', 'Bahrain', 'Manama', 'AS', '.bh', 'BHD', 'Dinar', '973', '####|###', '^(\\\\d{3}\\\\d?)$', 'ar-BH,en,fa,ur', ' ']\n",
      "http://example.webscraping.com/places/default/view/Bahamas-17 ['13,940 square kilometres', '301,790', 'BS', 'Bahamas', 'Nassau', 'NA', '.bs', 'BSD', 'Dollar', '+1-242', '', '', 'en-BS', ' ']\n",
      "http://example.webscraping.com/places/default/view/Azerbaijan-16 ['86,600 square kilometres', '8,303,512', 'AZ', 'Azerbaijan', 'Baku', 'AS', '.az', 'AZN', 'Manat', '994', 'AZ ####', '^(?:AZ)*(\\\\d{4})$', 'az,ru,hy', 'GE IR AM TR RU ']\n",
      "http://example.webscraping.com/places/default/view/Austria-15 ['83,858 square kilometres', '8,205,000', 'AT', 'Austria', 'Vienna', 'EU', '.at', 'EUR', 'Euro', '43', '####', '^(\\\\d{4})$', 'de-AT,hr,hu,sl', 'CH DE HU SK CZ IT SI LI ']\n",
      "http://example.webscraping.com/places/default/view/Australia-14 ['7,686,850 square kilometres', '21,515,754', 'AU', 'Australia', 'Canberra', 'OC', '.au', 'AUD', 'Dollar', '61', '####', '^(\\\\d{4})$', 'en-AU', ' ']\n",
      "http://example.webscraping.com/places/default/view/Aruba-13 ['193 square kilometres', '71,566', 'AW', 'Aruba', 'Oranjestad', 'NA', '.aw', 'AWG', 'Guilder', '297', '', '', 'nl-AW,es,en', ' ']\n",
      "http://example.webscraping.com/places/default/view/Armenia-12 ['29,800 square kilometres', '2,968,000', 'AM', 'Armenia', 'Yerevan', 'AS', '.am', 'AMD', 'Dram', '374', '######', '^(\\\\d{6})$', 'hy', 'GE IR AZ TR ']\n",
      "http://example.webscraping.com/places/default/view/Argentina-11 ['2,766,890 square kilometres', '41,343,201', 'AR', 'Argentina', 'Buenos Aires', 'SA', '.ar', 'ARS', 'Peso', '54', '@####@@@', '^([A-Z]\\\\d{4}[A-Z]{3})$', 'es-AR,en,it,de,fr,gn', 'CL BO UY PY BR ']\n",
      "http://example.webscraping.com/places/default/view/Antigua-and-Barbuda-10 ['443 square kilometres', '86,754', 'AG', 'Antigua and Barbuda', \"St. John's\", 'NA', '.ag', 'XCD', 'Dollar', '+1-268', '', '', 'en-AG', ' ']\n",
      "http://example.webscraping.com/places/default/view/Antarctica-9 ['14,000,000 square kilometres', '0', 'AQ', 'Antarctica', '', 'AN', '.aq', '', '', '', '', '', '', ' ']\n",
      "http://example.webscraping.com/places/default/view/Anguilla-8 ['102 square kilometres', '13,254', 'AI', 'Anguilla', 'The Valley', 'NA', '.ai', 'XCD', 'Dollar', '+1-264', '', '', 'en-AI', ' ']\n",
      "http://example.webscraping.com/places/default/view/Angola-7 ['1,246,700 square kilometres', '13,068,161', 'AO', 'Angola', 'Luanda', 'AF', '.ao', 'AOA', 'Kwanza', '244', '', '', 'pt-AO', 'CD NA ZM CG ']\n",
      "http://example.webscraping.com/places/default/view/Andorra-6 ['468 square kilometres', '84,000', 'AD', 'Andorra', 'Andorra la Vella', 'EU', '.ad', 'EUR', 'Euro', '376', 'AD###', '^(?:AD)*(\\\\d{3})$', 'ca', 'ES FR ']\n",
      "http://example.webscraping.com/places/default/view/American-Samoa-5 ['199 square kilometres', '57,881', 'AS', 'American Samoa', 'Pago Pago', 'OC', '.as', 'USD', 'Dollar', '+1-684', '', '', 'en-AS,sm,to', ' ']\n",
      "http://example.webscraping.com/places/default/view/Algeria-4 ['2,381,740 square kilometres', '34,586,184', 'DZ', 'Algeria', 'Algiers', 'AF', '.dz', 'DZD', 'Dinar', '213', '#####', '^(\\\\d{5})$', 'ar-DZ', 'NE EH LY MR TN MA ML ']\n",
      "http://example.webscraping.com/places/default/view/Albania-3 ['28,748 square kilometres', '2,986,952', 'AL', 'Albania', 'Tirana', 'EU', '.al', 'ALL', 'Lek', '355', '', '', 'sq,el', 'MK GR CS ME RS XK ']\n",
      "http://example.webscraping.com/places/default/view/Aland-Islands-2 ['1,580 square kilometres', '26,711', 'AX', 'Aland Islands', 'Mariehamn', 'EU', '.ax', 'EUR', 'Euro', '+358-18', '#####', '^(?:FI)*(\\\\d{5})$', 'sv-AX', ' ']\n",
      "http://example.webscraping.com/places/default/view/Afghanistan-1 ['647,500 square kilometres', '29,121,286', 'AF', 'Afghanistan', 'Kabul', 'AS', '.af', 'AFN', 'Afghani', '93', '', '', 'fa-AF,ps,uz-AF,tk', 'TM CN IR TJ PK UZ ']\n",
      "1.41 seconds\n"
     ]
    }
   ],
   "source": [
    "d = MongoCache(compress=False)\n",
    "start = time.time() # record start time of scrape\n",
    "link_crawler('http://example.webscraping.com','/places/default/(view|index)',max_depth=-1, scrape_callback=scrape_callback, cache=d)    \n",
    "end = time.time()\n",
    "print('%.2f seconds' % (end-start)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MongoCache:\n",
    "    def __init__(self, client=None, compress=False, expires=timedelta(days=30)):\n",
    "        # if a client object is not passed then try connecting to mongodb at the default localhost port\n",
    "        self.client = MongoClient('localhost', 27017) if client is None else client\n",
    "        # create collection to store cached webpages, which is the equivalent of a table in a relational database\n",
    "        self.db = self.client.cache\n",
    "        self.compress = compress\n",
    "        # create index to expire cached webpages\n",
    "        self.db.webpage.create_index('timestamp', expireAfterSeconds=expires.total_seconds())\n",
    "    def __getitem__(self, url):\n",
    "        \"\"\"\n",
    "        Load value at this url\n",
    "        \"\"\"\n",
    "        if self.compress:\n",
    "            url += '(compress)'\n",
    "        record = self.db.webpage.find_one({'_id': url})\n",
    "        if record:\n",
    "            if self.compress:\n",
    "                return pickle.loads(zlib.decompress(record['result']))\n",
    "            return record['result']\n",
    "        else:\n",
    "            raise KeyError(url + ' does not exist')\n",
    "    def __setitem__(self, url, result):\n",
    "        \"\"\"\n",
    "        Save value for this url\n",
    "        \"\"\"\n",
    "        if self.compress:\n",
    "            result = Binary(zlib.compress(pickle.dumps(result)))\n",
    "            url += '(compress)'\n",
    "        record = {'result': result, 'timestamp': datetime.utcnow()}\n",
    "        self.db.webpage.update({'_id': url}, {'$set': record}, upsert=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
